window.onload = function(){
    // 对象收编变量
    var bird = {
        // 天空背景定位偏移量
        skyPosition: 0,
        // 天空移动的步长
        skyStep: 2,
        // 小鸟原来距离顶部的长度
        birdTop:235,
        // 开始按钮的颜色类名
        startColor:"white",
        // 游戏是否游戏开始的标识符
        startFlag:false,
        // 小鸟下落的步长
        birdStepY:0,
        // 上边界
        minTop:0,
        // 下边界
        maxTop: 570,
        // 定时器标识符
        timer:null,
        // 生成柱子的对数
        pipeLength:7,
        // 存放柱子dom元素的数组
        pipeArr:[],
        // 最后一根柱子的索引号
        pipeLastIndex: 6, 
        // 当前分数
        score: 0,
        // 排行榜数据
        scoreArr:[],

        // 初始化的方法
        init:function(){
            this.initData();
            this.animate();
            this.handleStart();
            this.handleClick();
            this.handleRestart();

            // 判断当前会话中是否存在play数据
            if( sessionStorage.getItem("play") ){
                this.start();
            }
        },

        // 初始化数据的方法
        initData:function(){
            this.el = document.getElementById("game");
            this.oBird = this.el.getElementsByClassName("bird")[0];
            this.oStart = this.el.getElementsByClassName("start")[0];
            this.oScore = this.el.getElementsByClassName("score")[0];
            this.oMask = this.el.getElementsByClassName("mask")[0];
            this.oEnd = this.el.getElementsByClassName("end")[0];
            this.oFinalScore = this.el.getElementsByClassName("final-score")[0];
            this.oRankList = this.el.getElementsByClassName("rank-list")[0];
            this.oRestart = this.el.getElementsByClassName("restart")[0];

            // 获取本地存储中的数据
            this.scoreArr = this.getScore();
        },

        // 管理所有动画的方法
        animate:function(){
            // 声明一个变量,用于计数
            var count = 0;

            // 缓存this
            var self = this;

            // 开启定时器
            this.timer = setInterval(function(){
                // 调用天空移动的方法
                self.skyMove();

                // 游戏开始的时候
                if( self.startFlag ){
                    // 小鸟开始降落
                    self.birdDrop();
                    // 柱子移动
                    self.pipeMove();
                }

                // count自加1
                count++;

                // count是10的倍数的时候
                if( count % 10 === 0 ){
                    // 调用小鸟煽动翅膀的方法
                    self.birdFly( count );
                    
                    if( !self.startFlag ){// 游戏未开始的时候
                        // 调用小鸟跳跃的方法
                        self.birdJump();
                        // 调用开始按钮跳动的方法
                        self.startBound();
                    }
                }

            }, 30 );
        },

        // 天空移动的方法
        skyMove:function(){
            this.skyPosition -= this.skyStep;
            this.el.style.backgroundPositionX = this.skyPosition + "px";
        },

        // 小鸟跳动的方法
        birdJump:function(){
            this.birdTop = this.birdTop === 220 ? 260 : 220;
            this.oBird.style.top = this.birdTop + "px";
        },

        // 小鸟煽动翅膀的方法
        birdFly:function( count ){
            this.oBird.style.backgroundPositionX = count % 3 * -30 + "px";
        },

        // 开始按钮跳动的方法
        startBound:function(){
            // 上一次的颜色类名
            var prevColor = this.startColor;
            //  修改颜色类名
            this.startColor = this.startColor === "blue" ? "white" : "blue";
            // 删除上一次颜色类名
            this.oStart.classList.remove("start-" + prevColor );
            // 添加新的颜色类名
            this.oStart.classList.add("start-" + this.startColor );
        },

        // 小鸟下落的函数
        birdDrop:function(){
            this.birdTop += ++this.birdStepY;
            this.oBird.style.top = this.birdTop + "px";

            // 小鸟碰撞检测的函数
            this.judgeKnock();

            // 成功通过柱子加分的函数
            this.addScore();
        },

        // 通过柱子以后加分的函数
        addScore:function(){
            var index = this.score % this.pipeLength;
            var pipeX = this.pipeArr[index].up.offsetLeft;

            if( pipeX < 13 ){
                this.score++;
                this.oScore.innerText = this.score;
            }
        },

        // 小鸟碰撞检测的函数
        judgeKnock:function(){
            // 边界碰撞判断
            this.judgeBoundary();
            // 柱子碰撞判断
            this.judgePipe();
        },

        // 边界碰撞判断的函数
        judgeBoundary:function(){
            if( this.birdTop <= this.minTop || this.birdTop >= this.maxTop ){
                this.failGame();
            }
        },

        // 游戏结束的函数
        failGame:function(){
            console.log("游戏结束");
            // 清除定时器
            window.clearInterval( this.timer );

            // 显示遮罩层
            this.oMask.style.display = "block";
            // 显示结束层
            this.oEnd.style.display = "block";
            // 隐藏分数层
            this.oScore.style.display = "none";
            // 隐藏小鸟
            this.oBird.style.display = "none";
            // 设置最终分数
            this.oFinalScore.innerText = this.score;

            // 设置分数数据的函数
            this.setScore();

            // 渲染排行榜列表
            this.renderRankList();
        },

        // 获取分数数据的函数
        getScore:function(){
            var scoreArr = getLocal("score");
            return scoreArr ? scoreArr : [];
        },

        // 设置分数数据的函数
        setScore:function(){
            // 添加数据
            this.scoreArr.push({
                score: this.score,
                time: this.getDate()
            });

            // 降序排序
            this.scoreArr.sort(function( a, b ){
                return b.score - a.score;
            });

            // 限制数组长度,只要8个长度
            this.scoreArr.length = this.scoreArr.length > 8 ? 8 : this.scoreArr.length;

            // 设置本地存储
            setLocal("score" , this.scoreArr );
        },

        // 零填充函数
        zeroFill:function( num ){
            return num < 10 ? "0" + num : num; 
        },

        // 获取当前的日期时间
        getDate:function(){
            var d = new Date();
            var year = d.getFullYear();
            var month = this.zeroFill( d.getMonth() + 1 );
            var day = this.zeroFill( d.getDate() );
            var hour = this.zeroFill( d.getHours() );
            var minte = this.zeroFill( d.getMinutes() );
            var second = this.zeroFill( d.getSeconds() );

            return `${year}.${month}.${day} ${hour}:${minte}:${second}`;
        },

        // 渲染排行榜列表的函数
        renderRankList:function(){
            // 定义一个模板字符串
            var htmlStr = ``;

            // 循环遍历
            for( var i = 0; i < this.scoreArr.length; i++ ){
                // 定义一个degreeClass变量,拼接类名
                var degreeClass = ``;
                switch( i ){
                    case 0:
                        degreeClass = "first";
                    break;
                    
                    case 1:
                        degreeClass = "second";
                    break;

                    case 2:
                        degreeClass = "third";
                    break;
                }

                // 拼接字符串
                htmlStr += `
                <li class="rank-item">
                    <span class="rank-degree ${degreeClass}">${i + 1}</span>
                    <span class="rank-score">${this.scoreArr[i].score}</span>
                    <span class="rank-title">${this.scoreArr[i].time}</span>
                </li>
                `;
            }

            // 设置排行榜标签内容
            this.oRankList.innerHTML = htmlStr;
        },

        // 柱子碰撞判断的函数
        judgePipe:function(){
            // 根据分数算出当前通过柱子的索引号
            var index = this.score % this.pipeLength;
            // 求出对应索引号的柱子的left值
            var pipeX = this.pipeArr[index].up.offsetLeft;
            // 求出对应索引号的柱子的安全top值 
            var pipeY = this.pipeArr[index].y;
            // 小鸟的top值
            var birdY = this.birdTop;

            // pipeX是柱子的left值
            if( pipeX <= 95 && pipeX >= 13 ){// 是一个危险的left值
                if( birdY <= pipeY[0] || birdY >= pipeY[1] ){
                    this.failGame();
                }
            }
        },

        // 生成柱子的函数
        // x为柱子的左偏移量
        createPipe:function( x ){
            // 设定上下两个柱子之间的距离固定为150px高
            
            // 柱子最低高度为: 50 
            // 柱子最高高度为: (600 - 150) / 2 = 450 / 2 = 225 

            /* // 上柱子+下柱子的高度总共为 450  
            var upHeight = this.getRandom( 50, 225 );
            var downHeight = 450 - upHeight;

            // 上柱子
            var oDiv1 = document.createElement("div");
            oDiv1.classList.add("pipe");
            oDiv1.classList.add("pipe-up");
            oDiv1.style.height = upHeight + "px";
            oDiv1.style.left = x + "px";
            this.el.appendChild( oDiv1 );

            // 下柱子
            var oDiv2 = document.createElement("div");
            oDiv2.classList.add("pipe");
            oDiv2.classList.add("pipe-down");
            oDiv2.style.height = downHeight + "px";
            oDiv2.style.left = x + "px";
            this.el.appendChild( oDiv2 ); */



            // 设定上下两个柱子之间的距离固定为150px高
            
            // 柱子最低高度为: 50 
            // 柱子最高高度为: (600 - 150) / 2 = 450 / 2 = 225 

            // 上柱子+下柱子的高度总共为 450  
            var upHeight = getRandom( 50, 225 );
            var downHeight = 450 - upHeight;

            // 上柱子
            var oUpPipe = creatEle("div", ["pipe","pipe-up"], {
                left : x+"px",
                height: upHeight + "px"
            });

            // 下柱子
            var oDownPipe = creatEle("div", ["pipe","pipe-down"], {
                left : x+"px",
                height:downHeight + "px"
            });

            this.el.appendChild( oUpPipe );
            this.el.appendChild( oDownPipe );

            // 把数组添加到数组中
            this.pipeArr.push( {
                up:oUpPipe,
                down:oDownPipe,
                // y是安全范围top值
                y:[upHeight, upHeight + 150 - 30]
            } );
        },

        // 柱子移动的函数
        pipeMove:function(){
            for(var i = 0; i < this.pipeArr.length; i++ ){
                // 获取上柱子的dom对象
                var oUpPipe = this.pipeArr[i].up;
                // 获取下柱子的dom对象
                var oDownPipe = this.pipeArr[i].down;
                // 原来的offsetLeft的基础上减去天空移动的步长
                var x = oUpPipe.offsetLeft - this.skyStep;

                if( x < -52 ){// 当柱子的x值小于-52的时候
                    // 得到最后一个柱子的offsetLeft值
                    var lastPipeLeft = this.pipeArr[this.pipeLastIndex].up.offsetLeft;
                    oUpPipe.style.left = lastPipeLeft + 300 + "px";
                    oDownPipe.style.left = lastPipeLeft + 300 + "px";

                    // 更新最后一个柱子的索引号
                    this.pipeLastIndex = i;

                    // 跳过当前本地循环
                    continue;
                }

                // 设置柱子的left属性
                oUpPipe.style.left = x + "px";
                oDownPipe.style.left = x + "px";
            }
        },

        // 监听开始按钮的函数
        handleStart:function(){
            // 给按钮绑定点击事件
            this.oStart.onclick = this.start.bind( this );
        },

        // 开始游戏以后要做的事情对应的函数
        start:function(){
            // 显示分数层盒子
            this.oScore.style.display = "block";
            // 改变天空背景移动的速度
            this.skyStep = 5;
            // 隐藏开始游戏的按钮
            this.oStart.style.display = "none";
            // 改变游戏状态为开始
            this.startFlag = true;
            // 更改左偏移量
            this.oBird.style.left = "80px";
            // 取消小鸟身上的CSS过渡属性
            this.oBird.style.transition = "none";
            // 生成柱子
            for(var i = 0; i < this.pipeLength; i++ ){
                // 执行生成柱子的函数
                this.createPipe( 300 * (i + 1 ) );
            }
        },

        // 监听#game父元素点击事件
        handleClick:function(){
            // 缓存this
            var self = this;
            // 绑定事件
            this.el.onclick = function( e ){
                // 获取触发事件的目标对象
                var dom = e.target;
                // 判断这个目标对象身上是否包含.start类名 
                var isStart = dom.classList.contains("start"); 
                // 点击的不是开始按钮
                if( !isStart ){
                    // 小鸟往上,修改小鸟下落的步长为负
                    self.birdStepY = -10;
                }
            }
        },

        // 监听重新开始游戏按钮的点击事件
        handleRestart:function(){
            this.oRestart.onclick = function(){
                // 当前会话中保存数据
                window.sessionStorage.setItem("play", true );
                // 重新刷新页面
                window.location.reload();
            }
        }

    }

    bird.init();
}